# Otus Nosql

Цель:
В результате выполнения ДЗ вы настроите реплицирование и шардирование, аутентификацию в кластере и проверите отказоустойчивость.


Описание/Пошаговая инструкция выполнения домашнего задания:
Необходимо:

- построить шардированный кластер из 3 кластерных нод( по 3 инстанса с репликацией) и с кластером конфига(3 инстанса);
- добавить балансировку, нагрузить данными, выбрать хороший ключ шардирования, посмотреть как данные перебалансируются между шардами;
- поронять разные инстансы, посмотреть, что будет происходить, поднять обратно. Описать что произошло.
- настроить аутентификацию и многоролевой доступ;
Формат сдачи - readme с описанием алгоритма действий, результатами и проблемами.




1. построить шардированный кластер из 3 кластерных нод( по 3 инстанса с репликацией) и с кластером конфига(3 инстанса);
собираем кластер локально через докер
docker-compose -f ./mongodb-lab.yml up --wait

Запуск
docker-compose -f ./docker-compose.shard.yml up -d

Инициализация
// Инциализируем первую конфиг реплику
rs.initiate({
  "_id" : "config-replica-set", 
  members : [
    {"_id" : 0, priority : 3, host : "mongo-configsvr-1:40001"},
    {"_id" : 1, host : "mongo-configsvr-2:40002"},
    {"_id" : 2, host : "mongo-configsvr-3:40003" }
  ]
});

// Инициализируем шардинги

rs.initiate({
  "_id" : "shard-replica-set-1", 
  members : [
    {"_id" : 0, priority : 3, host : "mongo-shard-1-rs-1:40011"},
    {"_id" : 1, host : "mongo-shard-1-rs-2:40012"},
    {"_id" : 2, host : "mongo-shard-1-rs-3:40013" }
  ]
});

rs.initiate({
  "_id" : "shard-replica-set-2", 
  members : [
    {"_id" : 0, priority : 3, host : "mongo-shard-2-rs-1:40021"},
    {"_id" : 1, host : "mongo-shard-2-rs-2:40022"},
    {"_id" : 2, host : "mongo-shard-2-rs-3:40023" }
  ]
});


2. добавить балансировку, нагрузить данными, выбрать хороший ключ шардирования, посмотреть как данные перебалансируются между шардами
docker exec -it mongos-shard bash

> sh.addShard("shard-replica-set-1/mongo-shard-1-rs-1:40011,mongo-shard-1-rs-2:40012,mongo-shard-1-rs-3:40013")
> sh.addShard("shard-replica-set-2/mongo-shard-2-rs-1:40021,mongo-shard-2-rs-2:40022,mongo-shard-2-rs-3:40023")
> sh.status()


use bank
sh.enableSharding("bank")

use config
 db.settings.updateOne(
   { _id: "chunksize" },
   { $set: { _id: "chunksize", value: 1 } },
   { upsert: true }
)

use bank
for (var i=0; i<100200; i++) { db.tickets2.insertOne({name: "Max ammout of cost tickets", amount: Math.random()*100}) }
//получим 100200 документов

> db.tickets2.createIndex({amount: 1})
> db.tickets2.stats()
> 
![Alt text](image.png)

-- use admin
-- db.runCommand({shardCollection: "bank.tickets", key: {amount: 1}})
> sh.status()
![Alt text](image-2.png)
> sh.balancerCollectionStatus("bank.tickets")
![Alt text](image-1.png)
> sh.splitFind( "bank.tickets", { "amount": "50" } )

![Alt text](image-3.png)

 
3. поронять разные инстансы, посмотреть, что будет происходить, поднять обратно. Описать что произошло.
выключения primary ноды приводит к перевыборам - в этот момент данные не добавить, при возвращении приходит как secondary и проходят перевыборы. Если вес заранее не указать при запуске кластера - то получается рандом.

4. настроить аутентификацию и многоролевой доступ;

# В MongoDB shell
use admin

# Создание администратора
db.createUser({
  user: "adminUser",
  pwd: "adminPassword",
  roles: ["root"]
})

# Переключение на базу данных testDB
use testDB

# Создание пользователя с ролью для шардированной коллекции
db.createUser({
  user: "shardUser",
  pwd: "shardPassword",
  roles: [
    { role: "readWrite", db: "testDB" },
    { role: "read", db: "config" }
  ]
})
Здесь создается администратор с именем adminUser и паролем adminPassword, а также пользователь с именем shardUser, паролем shardPassword и ролью для чтения и записи в базе данных testDB и ролью для чтения в базе данных config.